package com.xtayfjpk.guava.test;

import com.google.common.base.Function;
import com.google.common.base.Optional;

public class Optionals {
	
	public static <T, U> Optional<T> bind(Optional<T> value, Function<T, Optional<T>> function) {
		if(value.isPresent()) {
			return function.apply(value.get());
		}
		return Optional.absent();
	}
	
	public static Function<String, Optional<String>> getCountryFromProvince() {
		return new Function<String, Optional<String>>() {
			@Override
			public Optional<String> apply(String input) {
				return Optional.fromNullable("Country Of " + input);
			}
		};
	}
	
	public static Function<String, Optional<String>> getProvinceFormCity() {
		return new Function<String, Optional<String>>() {
			@Override
			public Optional<String> apply(String input) {
				return Optional.fromNullable(null);
			}
		};
	}
	
	
	public static void main(String[] args) {
		String city = "GuangZhou";
		String value = 
				bind(bind(Optional.fromNullable(city), getProvinceFormCity()), 
				getCountryFromProvince()).orNull();
		
		System.out.println(value);
		
		value = FluentOptional.from(Optional.fromNullable(city)).bind(getCountryFromProvince()).bind(getCountryFromProvince()).orNull();
		System.out.println(value);
	}
	
	public static class FluentOptional <T> {
		private Optional<T> optional;
		
		private FluentOptional(Optional<T> optional) {
			this.optional = optional;
		}
		
		
		public static <T> FluentOptional<T> from(Optional<T> optional) {
			return new FluentOptional<T>(optional);
		}
		
		@SuppressWarnings("unchecked")
		public FluentOptional<T> bind(Function<T, Optional<T>> function) {
			if(optional.isPresent()) {
				return from(function.apply(optional.get()));
			}
			return (FluentOptional<T>) from(Optional.absent());
		}
		
		public T get() {
			return this.optional.get();
		}
		
		public T orNull() {
			return this.optional.orNull();
		}
	}
}
